package org.beetl.support;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

/**
 * 
 * DefaultGenericService
 * 
 * @param <T>
 *         the generic type
 */
public class DefaultGenericService<T> implements GenericService<T> {

 public DefaultGenericService() {
  entityClass = GenericUtils.getSuperClassGenericType(super.getClass());
  onSetting();
 }

 /**
  * On setting.
  */
 public void onSetting() {

 }

 /** 实体类类型(由构造方法自动赋值). */
 protected Class<?> entityClass;

 /**
  * Gets the entity class.
  *
  * @return the entity class
  */
 public Class<?> getEntityClass() {
  return entityClass;
 }

 /**
  * Sets the entity class.
  *
  * @param entityClass
  *         the entity class
  */
 public void setEntityClass(Class<?> entityClass) {
  this.entityClass = entityClass;
 }

 /** The dao. */
 protected GenericDao<T> dao;

 /**
  * Gets the dao.
  *
  * @return the dao
  */
 public GenericDao<T> getDao() {
  if (this.dao == null) {
   CommonSupport.throwIfNull(dao, "no dao ,no work!");
  }
  return dao;
 }

 /**
  * Sets the dao.
  *
  * @param dao
  *         the dao
  */
 public void setDao(GenericDao<T> dao) {
  this.dao = dao;
 }

 /**
  * 将技术异常翻译成用户能理解的消息。.
  *
  * @param result
  *         the result
  * @param e
  *         the e
  */
 public void onException(ResultSupport result, Throwable e) {
  LogSupport.logger.error("onException:{}", e);
  if (e instanceof NullPointerException) {
   result.onException("系统BUG(NullPointerException),通知开发人员修改。");
   return;
  }
  if (CommonSupport.containsIgnoreCase(e.getMessage(), "JDBC Connection")) {
   result.onException("数据库连接异常了,请稍后再试!");
   return;
  }
  result.onException(e);
 }

 /*
  * (non-Javadoc)
  * 
  * @see org.beetl.support.GenericService#get(java.io.Serializable)
  */
 public ItemResultSupport<T> get(Serializable id) {
  ItemResultSupport<T> result = new ItemResultSupport<T>();
  try {
   CommonSupport.throwIfNull(id, "no id ,no get!");
   result.setItem(this.getDao().get(id));
  } catch (Throwable e) {
   this.onException(result, e);
  }
  return result;
 }

 /*
  * (non-Javadoc)
  * 
  * @see org.beetl.support.GenericService#exists(java.io.Serializable)
  */
 public boolean exists(Serializable id) {
  return get(id).hasItem();
 }

 /**
  * On validate.
  *
  * @param result
  *         the result
  * @param entity
  *         the entity
  */
 public void onValidate(FormResultSupport result, T entity) {

 }

 /*
  * (non-Javadoc)
  * 
  * @see org.beetl.support.GenericService#save(java.lang.Object)
  */
 public FormResultSupport save(T entity) {
  FormResultSupport result = new FormResultSupport();
  try {
   this.onValidate(result, entity);
   if (result.hasError()) {
    result.onException("验证失败!");
    return result;
   }
   this.getDao().save(entity);
  } catch (Throwable e) {
   this.onException(result, e);
  }
  return result;
 }

 /*
  * (non-Javadoc)
  * 
  * @see org.beetl.support.GenericService#deleteByPK(java.io.Serializable)
  */
 public ResultSupport deleteByPK(Serializable id) {
  return deleteByPKs(new Serializable[] { id });
 }

 /*
  * (non-Javadoc)
  * 
  * @see org.beetl.support.GenericService#deleteByPKs(java.io.Serializable[])
  */
 public ResultSupport deleteByPKs(Serializable[] ids) {
  ResultSupport result = new ResultSupport();
  try {
   for (Serializable id : ids) {
    ItemResultSupport<T> existed = this.get(id);
    if (existed.hasItem()) {
     this.getDao().delete(existed.getItem());
    }
   }
  } catch (Throwable e) {
   this.onException(result, e);
  }
  return result;
 }

 /*
  * (non-Javadoc)
  * 
  * @see org.beetl.support.GenericService#deleteAll(java.util.Map)
  */
 public ResultSupport deleteAll(Map<String, Object> params) {
  ResultSupport result = new ResultSupport();
  try {
   this.getDao().deleteAll(params);
  } catch (Throwable e) {
   this.onException(result, e);
  }
  return result;
 }

 /*
  * (non-Javadoc)
  * 
  * @see org.beetl.support.GenericService#count(java.util.Map)
  */
 public ItemResultSupport<Long> count(Map<String, Object> params) {
  ItemResultSupport<Long> result = new ItemResultSupport<Long>();
  try {
   result.setItem(this.getDao().count(params));
  } catch (Throwable e) {
   this.onException(result, e);
  }
  return result;
 }

 /**
  * Count.
  *
  * @param params
  *         the params
  * @param countWhat
  *         the count what
  * @return the item result support< long>
  */
 public ItemResultSupport<Long> count(Map<String, Object> params, String countWhat) {
  ItemResultSupport<Long> result = new ItemResultSupport<Long>();
  try {
   result.setItem(this.getDao().count(params, countWhat));
  } catch (Throwable e) {
   this.onException(result, e);
  }
  return result;
 }

 /*
  * (non-Javadoc)
  * 
  * @see org.beetl.support.GenericService#query(org.beetl.support.QueryFilter)
  */
 public ListResultSupport<T> query(QueryFilter filter) {
  ListResultSupport<T> result = new ListResultSupport<T>();
  try {
   result.setRows(this.getDao().query(filter));
   result.setTotal(this.getDao().count(filter.getParams()));
  } catch (Throwable e) {
   this.onException(result, e);
  }
  return result;
 }

 /**
  * Query.
  *
  * @param filter
  *         the filter
  * @param queryWhat
  *         the query what
  * @param countWhat
  *         the count what
  * @return the list result support< t>
  */
 public ListResultSupport<T> query(QueryFilter filter, String queryWhat, String countWhat) {
  ListResultSupport<T> result = new ListResultSupport<T>();
  try {
   result.setRows(this.getDao().query(filter, queryWhat));
   result.setTotal(this.getDao().count(filter.getParams(), countWhat));
  } catch (Throwable e) {
   this.onException(result, e);
  }
  return result;
 }

 /*
  * (non-Javadoc)
  * 
  * @see
  * org.beetl.support.GenericService#queryOne(org.beetl.support.QueryFilter)
  */
 public ItemResultSupport<T> queryOne(QueryFilter filter) {
  ItemResultSupport<T> result = new ItemResultSupport<T>();
  try {
   List<T> items = this.getDao()
     .query(new QueryFilterBuilder().params(filter.getParams()).orderBy(filter.getOrderBy()).offset(filter.getOffset()).limit(1).build());
   if (!items.isEmpty()) {
    result.setItem(items.get(0));
   }
  } catch (Throwable e) {
   this.onException(result, e);
  }
  return result;
 }

 /**
  * Query one.
  *
  * @param filter
  *         the filter
  * @param queryWhat
  *         the query what
  * @return the item result support< t>
  */
 public ItemResultSupport<T> queryOne(QueryFilter filter, String queryWhat) {
  ItemResultSupport<T> result = new ItemResultSupport<T>();
  try {
   List<T> items = this.getDao().query(
     new QueryFilterBuilder().params(filter.getParams()).orderBy(filter.getOrderBy()).offset(filter.getOffset()).limit(1).build(),
     queryWhat);
   if (!items.isEmpty()) {
    result.setItem(items.get(0));
   }
  } catch (Throwable e) {
   this.onException(result, e);
  }
  return result;
 }

 /*
  * (non-Javadoc)
  * 
  * @see
  * org.beetl.support.GenericService#queryPage(org.beetl.support.QueryFilter,
  * int, int)
  */
 public PageResultSupport<T> queryPage(QueryFilter filter, int pageNum, int pageSize) {
  return queryPage(filter, pageNum, pageSize, "query", "count");
 }

 /*
  * (non-Javadoc)
  * 
  * @see
  * org.beetl.support.GenericService#queryPage(org.beetl.support.QueryFilter,
  * int, int, java.lang.String, java.lang.String)
  */
 public PageResultSupport<T> queryPage(QueryFilter filter, int pageNum, int pageSize, String queryWhat, String countWhat) {
  PageResultSupport<T> result = new PageResultSupport<T>();
  try {
   long total = this.getDao().count(filter.getParams(), countWhat);
   result.init(pageNum, pageSize, total);
   int offset = result.getOffset();
   result.setItems(this.getDao().query(
     new QueryFilterBuilder().params(filter.getParams()).orderBy(filter.getOrderBy()).offset(offset).limit(pageSize).build(), queryWhat));
  } catch (Throwable e) {
   this.onException(result, e);
  }
  return result;
 }

}
